package de.blinkt.openvpn;

import java.io.FileWriter;
import java.io.IOException;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.net.NetworkInfo;
import android.net.NetworkInfo.State;
import android.os.Handler;
import android.preference.PreferenceManager;
import de.blinkt.openvpn.VpnProfile.VpnNetworkInfo;

public class NetworkSateReceiver extends BroadcastReceiver {
	private NetworkInfo mLastNetwork = null;
	private OpenVpnManagementThread mManangement;

	private String lastStateMsg = null;

	public NetworkSateReceiver(OpenVpnManagementThread managementThread) {
		super();
		mManangement = managementThread;
	}

	@Override
	public void onReceive(Context context, Intent intent) {
		synchronized (mManangement) {
			NetworkInfo networkInfo = NetworkUtil.getCurrentNetworkInfo(context);
			SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
//			boolean sendusr1 = prefs.getBoolean("netchangereconnect", true);

			String netstatestring;
			if (networkInfo == null) {
				netstatestring = "not connected";
			} else {
				String subtype = networkInfo.getSubtypeName();
				if (subtype == null)
					subtype = "";
				
				String extrainfo = networkInfo.getExtraInfo();
				
				if (extrainfo == null)
					extrainfo = "";

				/*
				if(networkInfo.getType()==android.net.ConnectivityManager.TYPE_WIFI) {
					WifiManager wifiMgr = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);			
					WifiInfo wifiinfo = wifiMgr.getConnectionInfo();
					extrainfo+=wifiinfo.getBSSID();
				subtype += wifiinfo.getNetworkId();
				}*/

				netstatestring = String.format("%2$s %4$s to %1$s %3$s", networkInfo.getTypeName(), networkInfo.getDetailedState(), extrainfo, subtype);
			}

			
			

			
			if (mLastNetwork != null && networkInfo != null &&  networkInfo.getState() == State.CONNECTED && !NetworkUtil.sameNetwork(context, networkInfo, mLastNetwork)) {
				//We have connected to a new network. Record this as the latest network connected to 
				mLastNetwork = networkInfo;

				/*
				 * If reconnect is disabled, don't even try anything else
				 */
				if(!prefs.getBoolean("netchangereconnect", true)){
					mManangement.signalusr1();
				} else {
					
					//since global reconnect is enabled, assume that we will be reconnecting
					boolean reconnect = true;

					if(mManangement.getProfile().mRestrictReconnectToNetworks){
						reconnect = false;
						//if restrict is on, then don't reconnect if we aren't connecting to a restricted network.
						for (VpnNetworkInfo network : mManangement.getProfile().mRestrictedNetworksList) {
							if(NetworkUtil.networkMatches(context, networkInfo, network.mNetworkType, network.mNetworkSubtype, network.mNetworkName)){
								reconnect = true;
								break;
							}
						}
					}
					
					
					if(reconnect){
						//write out the profile config for the new network
						try {
							FileWriter cfg = new FileWriter(context.getCacheDir().getAbsolutePath() + "/" + VpnProfile.OVPNCONFIGFILE);
							cfg.write(mManangement.getProfile().getConfigFile(context));
							cfg.flush();
							cfg.close();
						} catch (IOException e) {
						}
					}
					
					final boolean fReconnect = reconnect;
					
					//TODO: Need an improved concurrency solution
					new Handler().postDelayed(new Runnable(){

						@Override
						public void run() {
							if(fReconnect){
								mManangement.reconnect();

							} else {
								mManangement.signalusr1();
							}							
						}
						
					}, 2000);
				}
				
			} else if(mLastNetwork == null && networkInfo != null &&  networkInfo.getState() == State.CONNECTED){
				mLastNetwork = networkInfo;
				mManangement.reconnect();
			} else if (networkInfo == null) {
				// Not connected, stop openvpn, set last connected network to no
				// network
				mLastNetwork = null;
				if (prefs.getBoolean("netchangereconnect", true))
					mManangement.signalusr1();
			}

			if (!netstatestring.equals(lastStateMsg)){
				OpenVPN.logInfo(R.string.netstatus, netstatestring);
			}
			
			lastStateMsg = netstatestring;
			
		}
	}

}
